<template>
    <el-card class="accounts">
      <div style="display: flex;justify-content: space-between;">
         <h3>
        钱包列表
        </h3>
        <div style="margin-top: 20px;text-align: right;">
            <el-button type="primary" @click="handleRefresh" v-if="!refreshing">刷新</el-button>
            <el-button type="warning" @click="handleStopRefresh" v-else>停止刷新</el-button>
            <el-button type="primary" @click="handleCollect" v-if="!collecting">归集</el-button>
            <el-button type="warning" @click="handleStopCollect" v-else>停止归集</el-button>
            <el-button type="success" @click="handleImport">导入</el-button>
            <el-button type="success" @click="handleExport">导出</el-button>
            <el-button type="danger" @click="handleClear">清除</el-button>
        </div>
        </div>
        <el-table
          :data="accounts"
          height="710"
          style="width: 100%"
          cell-class-name="logger-cell-style"
          empty-text="暂无执行记录"
          :summary-method="getSummaries"
          show-summary
        >
          <el-table-column prop="timestamp" label="时间" width="80" sortable>
            <template #default="{row}">
              {{ new Date(row.timestamp).toLocaleTimeString() }}
            </template>
          </el-table-column>
          <el-table-column prop="address" label="钱包"  width="150">
            <template #default="{row}">
              <div style="display: flex;flex-direction: column;font-size: 12px;font-family: 'Courier New', Courier, monospace;">
              <el-tooltip
                class="box-item"
                effect="dark"
                placement="top"
              >
              <template #content>{{row.address}}<br/>{{ row.privateKey }}</template>
              {{row.addr}}
              </el-tooltip>
            </div>
            </template>
          </el-table-column>
          <el-table-column prop="bnb" label="BNB" sortable/>
          <el-table-column prop="usdt" label="USDT" sortable/>
          <el-table-column prop="token" label="代币" sortable/>
          <el-table-column prop="status" label="操作" width="160" >
            <template #default="{row}">
              <el-button  type="danger" @click="handleRefreshOne(row)" size="small" :icon="Refresh"></el-button>
              <el-button  type="danger" @click="handleSell(row)" size="small">卖</el-button>
              <el-button  type="danger" @click="handleCollectOne(row)" size="small" >归</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-card>
</template>

<script setup>
import { onMounted, ref,inject,h} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Refresh,Wallet } from '@element-plus/icons-vue'
import { fmt } from '@/utils/string'
import { useCounterStore } from '@/stores/counterStore'
const counter = useCounterStore()

const logger = inject('logger');
const trade = inject('trade');

const accounts = ref([])
const activeName = ref('first')

const collecting = ref(false)
const refreshing = ref(false)


const WBNB_ADDRESS='0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
const USDT_ADDRESS='0x55d398326f99059fF775485246999027B3197955';

const formatter = (row, column) => {
  if (column === 'updatetime') {
    return new Date(row[column]).toLocaleString()
  }
  return row[column]
}

onMounted(() => {
  loadAccounts()
})

const loadAccounts = async () => {
  const storedAccounts = getAccounts();
  accounts.value=storedAccounts;
}

const getAccounts=()=>{
  const storedAccounts=JSON.parse(localStorage.getItem('accounts') || '[]');
  return storedAccounts;
  // throw new Error("获取钱包列表失败");
}

const getSellAccount=()=>{
  const storedAccounts = getAccounts();
  if (storedAccounts.length === 0) return null;
  
  // 按token降序排序并取前20
  const topAccounts = storedAccounts.slice()
    .sort((a, b) => b.token - a.token)
    .slice(0, 20);

  // 随机选取一个账户
  const randomIndex = Math.floor(Math.random() * topAccounts.length);
  return topAccounts[randomIndex];
}


const findAccount=(storeAccounts,address)=>{
  for(const account of storeAccounts){
    if(account.address==address){
      return account;
    }
  }
  return null;
}

const selectAccount=(mode,index)=>{
  const storedAccounts = getAccounts();
  if(storedAccounts.length===0){
    logger.value.error("列表","没有钱包");
    return null;
  }
  if(mode=='sequence'){
    logger.value.info("列表",`钱包【顺序】选择：${index}`);
    return storedAccounts[index];
  }
  if(mode=='random'){
    logger.value.info("列表",`钱包【随机】选择`);
    return storedAccounts[Math.floor(Math.random() * storedAccounts.length)];
  }
  throw new Error("钱包模式未设置");
}

const setAccounts=(_accounts)=>{
  localStorage.setItem('accounts', JSON.stringify(_accounts));
  // logger.value.info("列表","更新");
  loadAccounts();
}

const saveAccount = (_account) => {
  const storedAccounts = getAccounts();
  const size=storedAccounts.length;
  const new_account={id:size+1,
    address: _account.address, 
    addr: fmt(_account.address), 
    privateKey: _account.privateKey,
    bnb:0,
    usdt:0,
    token:0,
    timestamp:new Date(),
    updatetime:new Date()};
  storedAccounts.unshift(new_account);
  setAccounts(storedAccounts);
  logger.value.info("钱包",`保存\n${new_account.addr} `);
  return new_account;
}

const updateAccount = (account) => {
  const storedAccounts=getAccounts();
  const storedAccount=findAccount(storedAccounts,account.address);
  storedAccount.bnb=account.bnb;
  storedAccount.usdt=account.usdt;
  storedAccount.token=account.token;
  storedAccount.updatetime=account.updatetime;
  setAccounts(storedAccounts);
}


const  handleSell=async(account)=>{
  trade.value.sell(account)
}

const handleStopRefresh=()=>{
  logger.value.warn("列表","停止刷新.");
  refreshing.value=false;
}

const  handleRefresh=async()=>{
  const _accounts=getAccounts();
  refreshing.value=true;
  logger.value.trace("列表","刷新开始...");
  const walletAddresses=[];
  for (const account of _accounts) {
    walletAddresses.push(account.address);
  }
  const results= await trade.value.getAccountsBalances(walletAddresses);
  for (const account of _accounts) {
    account.updatetime=new Date();
    for(const item of results){
      if(item.address==account.address){
        if(item.symbol==='BNB'){
          account.bnb=item.balance;
          continue;
        }
        if(item.symbol==='USDT'){
          account.usdt=item.balance;
          continue;
        }
        if(item.symbol==='TOKEN'){
          account.token=item.balance;
          continue;
        }
      }
    }
  }
  refreshing.value=false;
  setAccounts(_accounts);
  logger.value.trace("列表","刷新完成.");
}

const  handleRefreshOne=async(account)=>{
  try{
    await refreshAccount(account);
  }catch(error){
    console.log(error);
  }
}

const  refreshAccount=async(account)=>{
  const begin=new Date().getTime();
  await logger.value.info("钱包",account.address+"\n刷新开始");
  const results= await trade.value.getAccountsBalances([account.address]);
  // await logger.value.trace("results",results);
  for(const item of results){
    if(item.symbol==='BNB'){
      account.bnb=item.balance;
      continue;
    }
    if(item.symbol==='USDT'){
      account.usdt=item.balance;
      continue;
    }
    if(item.symbol==='TOKEN'){
      account.token=item.balance;
      continue;
    }
  }
  account.updatetime=new Date();
  const end=new Date().getTime();
  await logger.value.info("钱包",`${account.address}\n刷新完成，耗时：${end-begin}ms`);
  updateAccount(account);
}

const refreshAccountByAddress=async(address)=>{
  const storeAccounts=getAccounts();
  const storeAccount=findAccount(storeAccounts,address);
  refreshAccount(storeAccount);
}


const handleStopCollect=async()=>{
  logger.value.warn("列表","归集停止");
  collecting.value=false;
}


const handleCollect=async()=>{
  collecting.value=true;
  const privateKeys=[];
  for (const account of accounts.value) {
    privateKeys.push(account.privateKey);
  }

  const config=trade.value.getConfig();

  
  if(config.poolType=='USDT'){
    await logger.value.info("列表","USDT归集开始...");
    await trade.value.batchCollectUSDT(privateKeys);
    await logger.value.success("列表","USDT归集完成");
  }

  await logger.value.info("列表","BNB归集开始...");
  await trade.value.batchCollectBNB(privateKeys);
  await logger.value.success("列表","BNB归集完成");

  collecting.value=false;
  await handleRefresh();
}

const handleCollectOne=async(account)=>{
  await collectOne(account);
}

const collectOne=async(account)=>{
  try{
    const [bnb,usdt,token]=await trade.value.getAccountTokens(account.privateKey);
    if(bnb.balance==0){
      await logger.value.warn("钱包",`${account.address}\nBNB余额不足`);
      await refreshAccount(account);
      return;
    }
    if(usdt.balance>0){
      logger.value.warn("钱包",`${account.address}\nUSDT余额不足`);
      await logger.value.info("钱包",`${account.address}\nUSDT归集开始...`);
      await trade.value.batchCollectUSDT([account.privateKey]);
      await logger.value.info("钱包",`${account.address}\nUSDT归集开始，USDT：${usdt.balance}`);
    }

    await logger.value.info("钱包",`${account.address}\nBNB归集开始...`);
    await trade.value.batchCollectBNB([account.privateKey]);
    await logger.value.info("钱包",`${account.address}\nBNB归集完成，BNB：${bnb.balance}`);
    await refreshAccount(account);
  }catch(err){
    logger.value.error("钱包",`${account.address}\n归集异常\n${err.message}`);
  }
}

const handleCreate=async()=>{
  const account=await trade.value.createAccount();
  saveAccount(account);
}


function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

const handleImport = () => {
  const input = document.createElement('input');
  input.type = 'file';
  input.accept = '.txt';
  
  input.onchange = e => {
    const file = e.target.files[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = event => {
      const content = event.target.result;
      const data=eval("(" + content + ")");
      setAccounts(data);
      console.log('读取到的文件内容:', data);
      // 这里可以添加对内容的处理逻辑
    };
    reader.onerror = error => {
      console.error('文件读取错误:', error);
    };
    reader.readAsText(file);
  };

  input.click();
};

const handleExport = () => {
  // const content = accounts.value.map(acc =>
  //   `地址: ${acc.address}\n私钥: ${acc.privateKey}\nBNB余额: ${acc.bnb}\n代币余额: ${acc.token}\n\n`
  // ).join('');

  const content = JSON.stringify(accounts.value, null, 2);
  const blob = new Blob([content], { type: 'text/plain' });
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = `accounts_${new Date().toISOString().slice(0,10)}.txt`;
  link.click();
  URL.revokeObjectURL(link.href);
};

const handleClear = () => {
  ElMessageBox.alert('确定清除钱包列表？清除后将不可恢复，慎重操作！！', '提示', {
    confirmButtonText: '确定清除',
    callback: (action) => {
      if(action==='confirm'){
        const accounts=getAccounts();
        localStorage.setItem('_accounts', JSON.stringify(accounts));
        setAccounts([]);
      }
    },
  })

};

const getSummaries = (param) => {
  const { columns, data } = param
  const sums= []
  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = h('div', { style: { textDecoration: 'underline' } }, [
        '合计',
      ])
      return
    }
    if(index === 2||index === 3){
      const values = data.map((item) => Number(item[column.property]))
      if (!values.every((value) => Number.isNaN(value))) {
        sums[index] = `${values.reduce((prev, curr) => {
          const value = Number(curr)
          if (!Number.isNaN(value)) {
            return prev + curr
          } else {
            return prev
          }
        }, 0)}`
      } else {
        sums[index] = 'N/A'
      }
    }
  })

  return sums
}

defineExpose({
  refreshAccountByAddress,
  selectAccount,
  saveAccount,
  refreshAccount,
  collectOne,getSellAccount })

</script>

<style>
.accounts{
  margin-bottom: 20px;
}
.tx-link {
  color: #409eff;
  text-decoration: none;
  &:hover {
    text-decoration: underline;
  }
}

.el-table td.el-table__cell div{
  word-wrap: break-word;
  overflow-wrap: break-word;
  white-space: pre-wrap;
}
</style>